/**
 * @file request 中间件
 */
import { URL } from "url"
import { extname } from "path"
import { parse } from "querystring"
import { readFile } from "#utils"
import { MiddlewareFunction, RequestLocation, RequestQuery, RouteObject } from "../../index.d.js"

/** 解析 request, 将 RequestLocation 插入中间件 */
export const requestLocationMiddleware: MiddlewareFunction = (options, next) => {
  const { request } = options
  const { url = "/", headers } = request // 获取请求地址 url, method
  const { host } = headers
  options.requestLocation = new URL(url, `http://${host}`)
  next()
}

/** 根据 method 解析参数 用 RequestQuery 插入中间件 */
export const requestQueryMiddleware: MiddlewareFunction = (options, next) => {
  const { request, requestLocation } = options
  const { method } = request
  const reqMethod = method?.toLowerCase()
  const { search, pathname } = requestLocation as RequestLocation
  const ext = extname(pathname)
  const requestQuery: RequestQuery = { method: reqMethod, extname: ext }
  options.requestQuery = requestQuery
  requestQuery.query = parse(search.replace(/^\?/, ""), "&", "=")
  if (reqMethod === "get") {
    next()
  } else {
    let postStr = ""
    request.on("data", data => {
      postStr += data
    })
    request.on("end", () => {
      requestQuery.postData = postStr ? JSON.parse(postStr) : {}
      next()
    })
  }
}

/** 根据 request 执行对应的方法 */
export const requestHandlerMiddleware: MiddlewareFunction = async (options, next) => {
  const { router, strict, requestLocation, requestQuery, readDirname = "" } = options

  const { pathname = "" } = requestLocation as RequestLocation
  const { extname } = requestQuery as RequestQuery

  let route: RouteObject | undefined = router[pathname]

  if (!route && strict) {
    if (pathname.endsWith("/")) route = router[pathname.replace(/\/$/, "")]
    else route = router[`${pathname}/`]
  }

  if (route) {
    const { handler } = route
    options.requestResult = await handler(options)
  } else if (extname) {
    const data = readFile(readDirname, pathname)
    if (data) {
      options.requestResult = { statusCode: 200, data }
    } else {
      options.requestResult = { statusCode: 404, data: "路由不存在" }
    }
  } else {
    options.requestResult = { statusCode: 404, data: "路由不存在" }
  }

  next()
}
